#include "sound.h"

#ifdef _DEBUG
# include "states.h"
# include "console.h" // eTB_Printf
#endif

/**
 * Wraps alGetError (...), such that if one error exists,
 *   ALL errors on the error stack are detected, and in
 *     debug mode, an execution trace (function name)
 *       is printed.
 *
**/
ALenum
eTB_alGetError (const char* trace)
{
  ALenum err = alGetError ();

  if (err != AL_NO_ERROR) {
#ifdef _DEBUG
    eTB_Printf ("OpenAL Error: 0x%04X - [%s]\n", err, trace);
#endif

    ALenum err_stack;
    while ((err_stack = alGetError ()) != AL_NO_ERROR) {
#ifdef _DEBUG
      eTB_Printf (" >> Secondary Error: 0x%04X - [%s]\n", err_stack, trace);
#endif
    }
  }

  return err;
}

OpenALContext* sound_context = NULL;

OpenALBuffer*
OpenALContext::createBuffer (void)
{
  ALuint buffer;
  alGenBuffers (1, &buffer);

  if (eTB_alGetError (__FUNCTION__) != AL_NO_ERROR) {
    /* TODO: Error Message. */
    return NULL;
  }

  return new OpenALBuffer (this, buffer);
}

OpenALSource*
OpenALContext::createSource (void)
{
  /* XXX: Something external is triggering an error! */
  //eTB_alGetError ("Before call to: " __FUNCTION__);

  ALuint source;
  alGenSources (1, &source);

  if (eTB_alGetError (__FUNCTION__) != AL_NO_ERROR) {
    /* TODO: Error Message. */
    return NULL;
  }

  return new OpenALSource (this, source);
}

bool
OpenALContext::destroySource (OpenALSource* source)
{
  if (! source)
    return false;

  if (alIsSource (source->handle_)) {
    ALuint sources [1];
    sources [0] = source->handle_;

    alDeleteSources (1, sources);

    if (eTB_alGetError (__FUNCTION__) != AL_NO_ERROR)
      return false;

    source->handle_  = NULL;
    source->context_ = NULL;

    delete source;

    return true;
  }

  return false;
}

bool
OpenALContext::destroyBuffer (OpenALBuffer* buffer)
{
  if (! buffer)
    return false;

  if (alIsBuffer (buffer->handle_)) {
    ALuint buffers [1];
    buffers [0] = buffer->handle_;

    alDeleteBuffers (1, buffers);

    if (eTB_alGetError (__FUNCTION__) != AL_NO_ERROR)
      return false;

    buffer->handle_  = NULL;
    buffer->context_ = NULL;

    delete buffer;

    return true;
  }

  return false;
}
